#include <assert.h>
#include "field.h"

using namespace slak::tetris;

Field::Field(int w, int h) : Tetrad(w,h), falling()
{
}

bool Field::drop(const Tetrad& f)
{
	int nx, ny;

	if (!falling.empty()) 
		renderFalling();

	ny = height - f.height;
	nx = (width-f.width)/2;

	falling = f;
	x = nx;
	y = ny;

	return !collides(x,y,falling);
}

void Field::renderFalling()
{
	for(int i=0; i<falling.width; i++)
		for(int j=0; j<falling.height; j++)
			if (falling.sq(i,j) != EMPTY)
				Tetrad::sq(x+i,y+j) = falling.sq(i,j);
	falling = Tetrad();
}

bool Field::moveFalling(int dx, int dy)
{
	assert(!falling.empty());

	int nx = x+dx, ny = y+dy;
	if (collides(nx,ny,falling))
		return false;

	x = nx;
	y = ny;

	return true;
}

square_state Field::sq(int i, int j) const
{
	assert(i<width);
	assert(j<height);

	if (falling.empty() 
	    || (i < x) || (i >= x+falling.width) 
	    || (j < y) || (j >= y+falling.height) 
	    || (falling.sq(i-x,j-y) == EMPTY))
		return Tetrad::sq(i,j);
	else
		return falling.sq(i-x,j-y);
}

bool Field::rotateFalling()
{
	Tetrad rot = falling.rotate();
	// recenter
	int cx = x + falling.cx, 
	    cy = y + falling.cy;
	int nx = cx - rot.cx, 
	    ny = cy - rot.cy;
	// if at Field top - re-fit vertically
	if (ny+rot.height > height)
		ny = height-rot.height;
	if (collides(nx,ny,rot))
		return false;
	falling = rot;
	x = nx;
	y = ny;
	return true;
}

void Field::clear()
{
	Tetrad::clear();
	falling = Tetrad();
}

